﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ServiceStack.Redis;
using System.Threading;
using System.Xml.Linq;
using System.IO;
using System.Web.Caching;
using Newtonsoft;
using yq.ICache;
using ServiceStack.Common.Web;
namespace yq.Redis
{
    /// <summary>
    /// Redis分布式缓存站点信息
    /// </summary>
    public class RedisManagers
    {
        /// <summary>
        /// 异常列表
        /// </summary>
        public static Dictionary<string, string> ExceptionReadLists = new Dictionary<string, string>();

        /// <summary>
        /// 内部共享锁
        /// </summary>
        private static readonly ReaderWriterLockSlim locker = new ReaderWriterLockSlim();

     
        private static Dictionary<string, PooledRedisClientManager> _ClientManagers = null;
        /// <summary>
        /// 对象池列表,本处供在第一次初始化时以写站点为准,建立所有调用池,后续无相应对象时,逐步建立
        /// string:以读写站点为主键
        /// </summary>
        private static Dictionary<string, PooledRedisClientManager> ClientManagers
        {
            get
            {
                if (_ClientManagers == null)
                {
                    _ClientManagers = new Dictionary<string, PooledRedisClientManager>();
                }

                return _ClientManagers;
            }
        }

     
        /// <summary>
        /// 根据对象的全路径名获取其所在的redis对象池
        /// </summary>
        /// <param name="classFullName"></param>
        /// <returns></returns>
        public static PooledRedisClientManager GetClientManager(ConfigHost config)
        {
            PooledRedisClientManager manager = null;

            locker.EnterReadLock();
            try
            {
                //从现有表与对象池关系中读取
                if (ClientManagers.TryGetValue(config.Key, out manager) == true)
                {
                    return manager;
                }
            }
            finally
            {
                locker.ExitReadLock();
            }


            //假如运行到此处,表示请求的对象为空,需要重新创建
            locker.EnterWriteLock();
            try
            {
                //如果查找不到,重新创建
                manager = CreateManager(new string[] { config.WriteHost }, config.ReadHosts, config.WriteCount, config.ReadCount);
                //添加到对象池中
                if (ClientManagers.ContainsKey(config.Key) == false)
                {
                    ClientManagers.Add(config.Key, manager);
                }
            }
            finally
            {
                locker.ExitWriteLock();
            }

            return manager;
        }

        /// <summary>
        /// 根据地址及端口号返回对象池,可能为null
        /// 请根据ConfigHost的key属性拼接
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public static PooledRedisClientManager GetClientManager(string key)
        {
            //根据端口号求取
            PooledRedisClientManager manager = null;
            ClientManagers.TryGetValue(key, out manager);
            return manager;
        }


        /// <summary>
        /// 创建池管理
        /// </summary>
        /// <param name="readWriteHosts">写地址,带端口号,如:127.0.0.1:1122</param>
        /// <param name="readOnlyHosts">只读地址,带端口号,如:127.0.0.1:1122</param>
        /// <param name="maxWritePoolSize">写的连接数量,默认为5</param>
        /// <param name="maxReadPoolSize">读的连接数量,默认为5</param>
        /// <returns></returns>
        private static PooledRedisClientManager CreateManager(string[] readWriteHosts, string[] readOnlyHosts, int maxWritePoolSize, int maxReadPoolSize)
        {
            //支持读写分离，均衡负载
            return new PooledRedisClientManager(readWriteHosts, readOnlyHosts, new RedisClientManagerConfig
            {
                MaxWritePoolSize = maxWritePoolSize,//“写”链接池链接数
                MaxReadPoolSize = maxReadPoolSize,//“读”链接池链接数
                AutoStart = true
            });
        }


    }
}
